package app.controller.wechat;

import app.circlerequest.ServerDownriverMsgHttp;
import app.circlerequest.Urloader;
import app.config.AppConf4Pur;
import app.controller.msgmanage.DeviceCache;
import app.controller.msgmanage.Stack4LockOpener;
import app.entity.UserSession;
import app.nbdevices.api.dto.BindResDto;
import app.nbdevices.api.dto.ResponseCode;
import app.nbdevices.utils.StackOperator;
import app.utils.*;
import app.utils.wechat.JsApiTicket;
import app.utils.wechat.WeChatJSAPITools;
import app.wechat.pojo.WeChat;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.mess.warningmess.Bean4WarnMessInfo;
import com.mess.warningmess.WarningMass;
import com.scyf.bean.Oauth2AccessToken;
import com.scyf.bean.SnsUserInfo;
import com.scyf.weixintool.WeiXinAuthorization;
import common.standard.table.*;
import common.standard.view.ViewNameEnum;
import door.controller.DoorController;
import org.springframework.http.*;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.RestTemplate;
import refactor.entity.AccessControl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import refactor.entity.*;
import refactor.entity.WeChatWorkCard;
import refactor.mapper.*;
import refactor.service.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 处理与微信有关的操作
 *
 * @author 杨健
 * @since 2019-07-25
 */
@Slf4j
@Controller()
//@Controller
public class WeChatOperator {
	@Autowired
	@Qualifier("wechat")
	private WeChat weChat;

	private IWeChatWorkCardService weChatWorkCardService;

	@Autowired
	public void setWeChatWorkCardService(IWeChatWorkCardService weChatWorkCardService) {
		this.weChatWorkCardService = weChatWorkCardService;
	}

	private IFacilitiesService facilitiesService;

	@Autowired
	public void setFacilitiesService(IFacilitiesService facilitiesService) {
		this.facilitiesService = facilitiesService;
	}

	private IDeviceService deviceService;

	@Autowired
	public void setDeviceService(IDeviceService deviceService) {
		this.deviceService = deviceService;
	}

	private IEventLogService eventLogService;

	@Autowired
	public void setEventLogService(IEventLogService eventLogService) {
		this.eventLogService = eventLogService;
	}

	private IModuleService moduleService;

	@Autowired
	public void setModuleService(IModuleService moduleService) {
		this.moduleService = moduleService;
	}

	private IFaultInfoService faultInfoService;

	@Autowired
	public void setFaultInfoService(IFaultInfoService faultInfoService) {
		this.faultInfoService = faultInfoService;
	}

	private IUnbindOpinionService unbindOpinionService;

	@Autowired
	public void setUnbindOpinionService(IUnbindOpinionService unbindOpinionService) {
		this.unbindOpinionService = unbindOpinionService;
	}

	private IDeviceFacilityService deviceFacilityService;

	@Autowired
	public void setDeviceFacilityService(IDeviceFacilityService deviceFacilityService) {
		this.deviceFacilityService = deviceFacilityService;
	}

	private IFacMonitoringService facMonitoringService;

	@Autowired
	public void setFacMonitoringService(IFacMonitoringService facMonitoringService) {
		this.facMonitoringService = facMonitoringService;
	}

	private IOrganizationService organizationService;

	@Autowired
	public void setOrganizationService(IOrganizationService organizationService) {
		this.organizationService = organizationService;
	}

	private UserMapper userMapper;

	@Autowired
	public void setUserMapper(UserMapper userMapper) {
		this.userMapper = userMapper;
	}

	private DeviceMapper deviceMapper;

	@Autowired
	public void setDeviceMapper(DeviceMapper deviceMapper) {
		this.deviceMapper = deviceMapper;
	}

	private IAccessControlService accessControlService;

	@Autowired
	public void setAccessControlService(IAccessControlService accessControlService) {
		this.accessControlService = accessControlService;
	}

	private IUserService userService;

	@Autowired
	public void setUserService(IUserService userService) {
		this.userService = userService;
	}


	@Autowired
	private DoorController doorController;

	@Autowired
	private ApplyRecordMapper applyRecordMapper;

//	@Autowired
//	private FacMonitoringMapper facMonitoringMapper;

	@Autowired
	private RegionMapper regionMapper;

	/**
	 * 添加设备
	 *
	 * @param name
	 * @param area 区域
	 * @param charger
	 * @param type 类型
	 * @param installor 安装者
	 * @param model
	 * @param session
	 * @param request
	 * @return
	 */
	@RequestMapping("/2/addFac")
	public String addFac(String name, String area, Integer charger, Integer type, Integer installor, Model model, HttpSession session, HttpServletRequest request){
		model.addAttribute(ModelAttributeEnum.BASE_PATH.getAttributeName(), BasePathCollector.getBasePathWithoutPort(request));

		UserSession userSession= (UserSession) session.getAttribute(Common.sessionUser);
        User userC = userMapper.selectById(charger);
        User userI = userMapper.selectById(installor);
		Module module = moduleService.getById(type);
		area=regionMapper.selectOne(new QueryWrapper<Region>().eq("id",userSession.getRegionId())).getName();
		Facilities fac=new Facilities(null,
				userSession.getRegionId(),
				userC.getId(),
				"",
				name,
				area,
				"",
				module.getName(),
				"",
				"",
				"",
				0L,
				0L,
				"1");

        facilitiesService.save(fac);

		if (installor !=0) {
			EventLog EventLog = new EventLog(0,
					module.getId(), //
					0,
					fac.getId(), //
					installor, //
					1,
					2, // 1
					"",
					"",
					"",
					"0", // 0
					System.currentTimeMillis(), // now
					System.currentTimeMillis() + 3600 * 24 * 1000, // 3t
					"",
					"");
            eventLogService.save(EventLog);
		}
		return "redirect:/2/devbindinfo";
	}

	@RequestMapping("/siotwx/unbindWechat")
	public void unbindWechat(HttpSession session,HttpServletResponse response){
		UserSession userSession= (UserSession) session.getAttribute(Common.sessionUser);
		Map<String, Object> map=new HashMap<>();
		if (userSession != null) {
			Integer id = userSession.getId();
			User user = userMapper.selectById(id);

			user.setOpenId("");
            user.setAvatar("");
            int update = userMapper.update(user, null);
			if (update > 0) {
				map.put("flag", true);
				session.setAttribute(Common.sessionUser, new UserSession(user));
				DataResponse.jsonResponse(response, map);
				return;
			}
			map.put("flag", false);
			DataResponse.jsonResponse(response, map);
			return;
		}
		map.put("flag", false);
		DataResponse.jsonResponse(response, map);
		return;
	}

	// 执行微信登陆
	@RequestMapping("/wlogin")
	public void wechatLogin(String code, HttpSession session, HttpServletResponse response, HttpServletRequest request)
			throws IOException {

		Oauth2AccessToken oauth2AccessToken = WeiXinAuthorization.getOauth2AccessToken(weChat.getAppId(),
				weChat.getAppSecret(), code);
		Map<String, Object> param = new HashMap<>();
		param.put(UserFieldEnum.OPEN_ID.getFieldName(), oauth2AccessToken.getOpenid());
		//param.put(UserFieldEnum.OPEN_ID.getFieldName(), "oYoyoowddvgdbgbng54dd5hdb4fb");
		List<User> userList = userMapper.selectByMap(param);
 		if (userList != null && !userList.isEmpty()) {
			User user = userList.get(0);
			if ("2".equals(user.getFrozen())) {
				response.sendRedirect(BasePathCollector.getBasePathWithoutPort(request) + "sos/msg");
				return;// "跳转到微信登陆进的主页";//TODO
			}
			session.setAttribute(Common.sessionUser, new UserSession(user));
			response.sendRedirect(BasePathCollector.getBasePathWithoutPort(request) + "3/wxindex");
			return;// "跳转到微信登陆进的主页";//TODO
		}
//		SnsUserInfo snsUserInfo = WeiXinAuthorization.getSnsUserInfo(oauth2AccessToken.getAccess_token(),
//				oauth2AccessToken.getOpenid());
//		String openid = snsUserInfo.getOpenid();
//		String headimgurl = snsUserInfo.getHeadimgurl();
//
//		String target = BasePathCollector.getBasePathWithoutPort(request) + "3/register?openId=" + openid
//				+ "&headimgurl=" + headimgurl;
//		response.sendRedirect(target);
//		return;// "跳转到注册页面";//TODO
	}

	@RequestMapping("/sos/msg")
	public String msg(Model model) {

		String msg = "您已注册，等待系统审核！<br> 需重新登陆！";
		model.addAttribute(ModelAttributeEnum.MESSAGE.getAttributeName(), msg);
		return "msg";
	}

	@RequestMapping("/{role}/register")
	public String register(@PathVariable("role") Integer role, String openid, String headimgurl, Model model,
			HttpServletRequest request) {
		model.addAttribute(ModelAttributeEnum.OPEN_ID.getAttributeName(), openid);
		model.addAttribute(ModelAttributeEnum.HEAD_IMAGE_URL.getAttributeName(), headimgurl);
		model.addAttribute(ModelAttributeEnum.ROLE.getAttributeName(), role);
		commonModelAdd(model, BasePathCollector.getBasePathWithoutPort(request), "工人注册");

		return "wechat/registerpersonal";
	}

	// 公司编码校验
	@RequestMapping("/orgcodecheker/{orgCode}")
	public void orgcodecheker(@PathVariable("orgCode") String orgCode, HttpServletResponse response) {
		Map<String, Object> params = new HashMap<>();
		List<Organization> org = organizationsSearchByCode(orgCode);
		params.clear();
		if (org != null && !org.isEmpty()) {
			params.put("key", true);
			params.put("org", org.get(0).getName());
		} else {
			params.put("key", false);
			params.put("org", "公司编码不存在");
		}
		DataResponse.jsonResponse(response, params);
	}

	private List<Organization> organizationsSearchByCode(@PathVariable("orgCode") String orgCode) {
		QueryWrapper<Organization> organizationQueryWrapper = new QueryWrapper<Organization>().eq(OrganizationFieldEnum.CODE.getFieldName(), orgCode.replace(" ", ""));
		return organizationService.list(organizationQueryWrapper);
	}

	@RequestMapping("/{role}/personalregister")
	public String personalregister(String orgCode, String cellPhone, String realName,
			@PathVariable("role") Integer role, String openid, String headImgUrl, Model model,
			HttpServletRequest request) {
		String msg = "您已注册，等待系统审核！<br> 需重新登陆！";
		model.addAttribute(ModelAttributeEnum.BASE_PATH.getAttributeName(), BasePathCollector.getBasePathWithoutPort(request));

		List<Organization> org = organizationsSearchByCode(orgCode);

		if (org != null && !org.isEmpty()) {
			User user = new User();
			user.setId(null).setOrganizationId(org.get(0).getId()).setRoleId(3).setRegionId(org.get(0).getRegionId())
					.setCode("")
					.setName(realName)
					.setPassword("")
					.setNameDigest("")
					.setPasswordDigest("")
					.setRealName(realName)
					.setSex("")
					.setIdCard("")
					.setPhoneNumber(cellPhone)
					.setEmail("")
					.setQq("")
					.setWeChat("")
					.setOpenId(openid)
					.setAvatar(headImgUrl)
					.setRegisterTime(System.currentTimeMillis())
					.setFrozen("2")
					.setRoleName("施工维护人员")
					.setAuthorityInfo("user");

			userMapper.insert(user);
		} else {
			msg = "公司编码有误<br> 请重新操作";
		}
		model.addAttribute(ModelAttributeEnum.MESSAGE.getAttributeName(), msg);
		return "msg";
	}

	// 展示工单数据
	@RequestMapping("/{role}/wxindex")
	public String workcardList(String mySearch, HttpSession session, Model model, HttpServletRequest request)
			throws Exception {
		WeChat w=weChat;
		UserSession user = (UserSession) session.getAttribute(Common.sessionUser);
		commonModelAdd(model, BasePathCollector.getBasePathWithoutPort(request), "工单");
		model.addAttribute(ModelAttributeEnum.WE_CHAT.getAttributeName(), weChat);

		// 获取权限//1.10注释
//		JsApiTicket jsApiTicket = WeChatJSAPITools.WeChatJSAPI(weChat.getAppId(), weChat.getAppSecret(), request,session);
		model.addAttribute(ModelAttributeEnum.OPEN_ID.getAttributeName(), user.getOpenId());
//		model.addAttribute(ModelAttributeEnum.SIGNATURE.getAttributeName(), jsApiTicket.getSignature());
//		model.addAttribute(ModelAttributeEnum.TIMESTAMP.getAttributeName(), jsApiTicket.getTimestamp());
//		model.addAttribute(ModelAttributeEnum.NONCE_STR.getAttributeName(), jsApiTicket.getNonce());

		if (user != null) {
//			Map<String, Object> params = new HashMap<>();
//			params.put(Wxworkcard.FieldName.workerId.toString(), user.getId());
//			if ("1".equals(mySearch)) {
//				params.put(Wxworkcard.FieldName.eventResult.toString(), "1");
//			} else if ("0".equals(mySearch)) {
//				params.put(Wxworkcard.FieldName.eventResult.toString(), "0");
//			} else {
//				mySearch = "-1";
//			}
			QueryWrapper<WeChatWorkCard> weChatWorkCardQueryWrapper = new QueryWrapper<WeChatWorkCard>().eq(WeChatWorkCardFieldEnum.WORKERID.getFieldName(), user.getId());
			if ("1".equals(mySearch) || "0".equals(mySearch)) {
				//eventResult与mySearch
				weChatWorkCardQueryWrapper = new QueryWrapper<WeChatWorkCard>().eq(WeChatWorkCardFieldEnum.WORKERID.getFieldName(), mySearch);
				mySearch = "-1";
			}
			List<WeChatWorkCard> list = weChatWorkCardService.list(weChatWorkCardQueryWrapper);
			model.addAttribute(ModelAttributeEnum.LIST.getAttributeName(), list);
			model.addAttribute(ModelAttributeEnum.MY_SEARCH.getAttributeName(), mySearch);
		}

		return ViewNameEnum.WECHAT_INDEX.getViewName();
	}

    // 展示工单数据
	@ResponseBody
    @RequestMapping("/api/getcardlist")
    public ResponseCode workcardListapi(String mySearch, String oppenId)
            throws Exception {
	        List<User> us=userMapper.selectList(new QueryWrapper<User>().eq("open_id",oppenId));
            QueryWrapper<WeChatWorkCard> weChatWorkCardQueryWrapper=null;
	        if(us.size()>0){
	            User user=us.get(0);
                if ("1".equals(mySearch) || "0".equals(mySearch)) {

                    //eventResult与mySearch
					if("0".equals(mySearch)){
						weChatWorkCardQueryWrapper = new QueryWrapper<WeChatWorkCard>().eq(WeChatWorkCardFieldEnum.DEVID.getFieldName(), "0")
								.eq(WeChatWorkCardFieldEnum.WORKERID.getFieldName(), user.getId());
					}else if("1".equals(mySearch)){
						weChatWorkCardQueryWrapper = new QueryWrapper<WeChatWorkCard>().ne(WeChatWorkCardFieldEnum.DEVID.getFieldName(), "0")
								.eq(WeChatWorkCardFieldEnum.WORKERID.getFieldName(), user.getId());
					}
                    mySearch = "-1";
                }else{
                    weChatWorkCardQueryWrapper = new QueryWrapper<WeChatWorkCard>().eq(WeChatWorkCardFieldEnum.WORKERID.getFieldName(), user.getId());
                }
            }
        return ResponseCode.success(weChatWorkCardService.list(weChatWorkCardQueryWrapper));
    }

	// 展示工单数据
	@RequestMapping("/{role}/wxindex2")
	public String workcardList2(String mySearch, HttpSession session, Model model, HttpServletRequest request)
			throws Exception {
		return workcardList(mySearch, session, model, request);
	}

	// 故障处理
	@RequestMapping("/{role}/managefault")
	public String managefault(HttpSession session, Model model, HttpServletRequest request) {
		UserSession user = (UserSession) session.getAttribute(Common.sessionUser);
		commonModelAdd(model, BasePathCollector.getBasePathWithoutPort(request), "故障处理");
		if (user != null) {
			QueryWrapper<FaultInfo> faultInfoQueryWrapper = new QueryWrapper<FaultInfo>().eq(FaultInfoFieldEnum.USERID.getFieldName(), user.getId()).eq(FaultInfoFieldEnum.RES.getFieldName(), "0");
			List<FaultInfo> list = faultInfoService.list(faultInfoQueryWrapper);
			model.addAttribute(ModelAttributeEnum.LIST.getAttributeName(), list);
		}
		return "wechat/managefault";
	}

	@RequestMapping("/{role}/devicebind")
	public String deviceBind(Model model, HttpServletRequest request, String longitude, String latitude,
							 String resultStr, Integer facId, String facDesc, Integer eventId, Integer modId, Long accuracy,
							 String poiResult, String operate, HttpSession session) {
		String message = "";
		model.addAttribute(ModelAttributeEnum.BASE_PATH.getAttributeName(), BasePathCollector.getBasePathWithoutPort(request));
		commonModelAdd(model, Common.appName, "绑定设备");

		String returnUrl = BasePathCollector.getBasePathWithoutPort(request) + "3/wxindex";

		// 标准化获取到的字符串数据
		longitude = longitude.toUpperCase().replaceAll(" ", "");
		latitude = latitude.toUpperCase().replaceAll(" ", "");
		resultStr = resultStr.toUpperCase().replaceAll(" ", "");

		log.info("longitude:" + longitude);
		log.info("latitude: " + latitude);
		log.info("accuracy: " + accuracy);
		log.info("resultStr: " + resultStr);
		log.info("facId: " + facId);
		log.info("facDesc: " + facDesc);
		log.info("eventId: " + eventId);
		log.info("modId: " + modId);
		log.info("poiResult: " + poiResult);

		// 用于判断设施是否将要绑定的应该绑定的类型的设备
		String mod = moduleService.getById(modId).getCode();
		String resultStrType = resultStr.substring(0, 1);

		if (operate == null) {
			model.addAttribute(ModelAttributeEnum.LONGITUDE.getAttributeName(), longitude);
			model.addAttribute(ModelAttributeEnum.LATITUDE.getAttributeName(), latitude);
			model.addAttribute(ModelAttributeEnum.ACCURACY.getAttributeName(), accuracy);
			model.addAttribute(ModelAttributeEnum.RESULT_STR.getAttributeName(), resultStr);
			model.addAttribute(ModelAttributeEnum.FAC_ID.getAttributeName(), facId);
			model.addAttribute(ModelAttributeEnum.FAC_DESC.getAttributeName(), facDesc);
			model.addAttribute(ModelAttributeEnum.EVENT_ID.getAttributeName(), eventId);
			model.addAttribute(ModelAttributeEnum.MOD_ID.getAttributeName(), modId);
			model.addAttribute(ModelAttributeEnum.POI_RESULT.getAttributeName(), poiResult);
			return "wechat/binddevice";
		}
		
		log.info("注意信号强度："+accuracy);
		
		/* 如果GPS信号不好 */
		if (accuracy > 40) {
			if (poiResult != null && !poiResult.equals("")) {
				String[] strArray = poiResult.split(",");

				longitude = strArray[0];
				latitude = strArray[1];
			}
		} else {
			try {
				// 将微信得到的wgs84坐标系经纬度转换为bd09坐标系经纬度
				String tmplnglat = new BaiduMapUtils().wgs84Tobd09(longitude, latitude);

				String[] tempArray = tmplnglat.split(",");
				longitude = tempArray[0];
				latitude = tempArray[1];
			} catch (Exception e) {

				message = "经纬坐标解析失败，请重新绑定！";
				return deviceBindCommonMessage(model, message, returnUrl);

			}
		}

		// 通过条件查找数据库中的设备
		Device deviceResult = null;
		// 从数据库查到的设备编码
		String resultDeviceCode = "";

		QueryWrapper<Device> deviceQueryWrapper = new QueryWrapper<Device>().eq(DeviceFieldEnum.CODE.getFieldName(), resultStr);
		List<Device> deviceList = deviceService.list(deviceQueryWrapper);
		//deviceService.save()
		if (deviceList != null && !deviceList.isEmpty()) {
			deviceResult = deviceList.get(0);
			resultDeviceCode = deviceResult.getCode();
		}

		// 从数据库查到的设施编码存放在这
		String resultFacilitiesDesc = "";

		// 通过id查找数据库设施表中的设施
		Facilities facilitiesResult = facilitiesService.getById(facId);
		if (facilitiesResult != null) {
			resultFacilitiesDesc = facilitiesResult.getDescription();
		}

		// 获取此用户所属公司买了哪些模块
		String purchases = "";

		if (AppConf4Pur.GetProperty(AppConf4Pur.DOOR)) {
			purchases += "DL";
		}
		if (AppConf4Pur.GetProperty(AppConf4Pur.WELL)) {
			purchases += "W";
		}
		if (AppConf4Pur.GetProperty(AppConf4Pur.ELE)) {
			purchases += "E";
		}

		// 获取用户id
		UserSession userSession = (UserSession) session.getAttribute(Common.sessionUser);
		int userId = userSession.getId();
		// 查找用户是否被冻结
		User userFro = userMapper.selectById(userId);
		if (!"0".equals(userFro.getFrozen())) {
			message = "您的账户已被冻结！";
			return deviceBindCommonMessage(model, message, returnUrl);
		} else if ("".equals(resultDeviceCode)) {
			message = "未找到设备！";
			return deviceBindCommonMessage(model, message, returnUrl);
		} else if ("".equals(resultFacilitiesDesc)) {
			message = "未找到设施！";
			return deviceBindCommonMessage(model, message, returnUrl);
		} else if (!"1".equals(facilitiesResult.getWorkStatus())) {
			message = "该设施已停用！";
			return deviceBindCommonMessage(model, message, returnUrl);
		} else if (deviceResult.getFacilitiesId() != 0) {
			message = "设备已经被绑定在其他设施上！";
			return deviceBindCommonMessage(model, message, returnUrl);
		} else if (!mod.equals(resultStrType)) {
			message = "请绑定工单要求的设备类型！";
			return deviceBindCommonMessage(model, message, returnUrl);
		} else if (!purchases.contains(resultStrType)) {
			message = "请购买对此模块的使用权限！";
			return deviceBindCommonMessage(model, message, returnUrl);
		} else {

			// 执行绑定
			// 将设施在表中的主键ID存入设备表,记录设备绑定时间
			deviceResult.setFacilitiesId(facilitiesResult.getId());
			deviceResult.setOnline(TimeUtils.getNowDateLong());
            deviceService.updateById(deviceResult);

			// 将经纬度存入设施表
			facilitiesResult.setLongitude(longitude);
			facilitiesResult.setLatitude(latitude);
			// 将定位精度存入设施表的endTime字段中
			facilitiesResult.setEndTime(accuracy);
			// 绑定之后更新时间
			facilitiesResult.setStartTime(TimeUtils.getNowDateLong());

            facilitiesService.updateById(facilitiesResult);

			message = "绑定成功！";
			log.info(message);

			// 在EventLog表中更新工单已处理的数据状态
			EventLog EventLog = eventLogService.getById(eventId);

			EventLog.setDeviceId(deviceResult.getId());
			EventLog.setResult("1");
			EventLog.setEndTime(TimeUtils.getNowDateLong());
			eventLogService.updateById(EventLog);
			log.info("绑定完成后更新EventLog表成功！");

			// 发送短信给负责人
			Module module = moduleService.getById(deviceResult.getModId());
			User user = userMapper.selectById(facilitiesResult.getUserId());
			String msg = "绑定成功";
			Bean4WarnMessInfo info = new Bean4WarnMessInfo(deviceResult.getCode(), module.getName(),
					facilitiesResult.getDescription(), "", user.getRealName(), user.getPhoneNumber(), msg);
			WarningMass.sendMess(info);
			model.addAttribute(ModelAttributeEnum.MESSAGE.getAttributeName(), message);
			model.addAttribute(ModelAttributeEnum.JUMP_TO_LOWER.getAttributeName(), returnUrl);

			return "redirect:https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx3ad01cbe5026a89a&redirect_uri="+BasePathCollector.getBasePathWithoutPort(request)+"wlogin&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect";
		}

	}

	@ResponseBody
    @RequestMapping("/api/devbind")
    public ResponseCode apiDeviceBind(String longitude, String latitude,
                                      String resultStr, Integer facId, String facDesc, Integer eventId, Integer modId, Long accuracy,
                                      String poiResult,String oppenId) {
        BindResDto dto=new BindResDto();
        String message = "";

        // 标准化获取到的字符串数据
        longitude = longitude.toUpperCase().replaceAll(" ", "");
        latitude = latitude.toUpperCase().replaceAll(" ", "");
        resultStr = resultStr.toUpperCase().replaceAll(" ", "");

        log.info("longitude:" + longitude);
        log.info("latitude: " + latitude);
        log.info("accuracy: " + accuracy);
        log.info("resultStr: " + resultStr);
        log.info("facId: " + facId);
        log.info("facDesc: " + facDesc);
        log.info("eventId: " + eventId);
        log.info("modId: " + modId);
        log.info("poiResult: " + poiResult);

        // 用于判断设施是否将要绑定的应该绑定的类型的设备
        String mod = moduleService.getById(modId).getCode();
        String resultStrType = resultStr.substring(0, 1);

        log.info("注意信号强度："+accuracy);

        /* 如果GPS信号不好 */
        if (accuracy > 40) {
            if (poiResult != null && !poiResult.equals("")) {
                String[] strArray = poiResult.split(",");

                longitude = strArray[0];
                latitude = strArray[1];
            }
        } else {
            try {
                // 将微信得到的wgs84坐标系经纬度转换为bd09坐标系经纬度
                String tmplnglat = new BaiduMapUtils().wgs84Tobd09(longitude, latitude);

                String[] tempArray = tmplnglat.split(",");
                longitude = tempArray[0];
                latitude = tempArray[1];
            } catch (Exception e) {
                message = "经纬坐标解析失败，请重新绑定！";
                dto.setIssucc(0);
                dto.setError_desc(message);
                return ResponseCode.success(dto);

            }
        }

        // 通过条件查找数据库中的设备
        Device deviceResult = null;
        // 从数据库查到的设备编码
        String resultDeviceCode = "";

        QueryWrapper<Device> deviceQueryWrapper = new QueryWrapper<Device>().eq(DeviceFieldEnum.CODE.getFieldName(), resultStr);
        List<Device> deviceList = deviceService.list(deviceQueryWrapper);
        //deviceService.save()
        if (deviceList != null && !deviceList.isEmpty()) {
            deviceResult = deviceList.get(0);
            resultDeviceCode = deviceResult.getCode();
        }

        // 从数据库查到的设施编码存放在这
        String resultFacilitiesDesc = "";

        // 通过id查找数据库设施表中的设施
        Facilities facilitiesResult = facilitiesService.getById(facId);
        if (facilitiesResult != null) {
            resultFacilitiesDesc = facilitiesResult.getDescription();
        }

        // 获取此用户所属公司买了哪些模块
        String purchases = "";

        if (AppConf4Pur.GetProperty(AppConf4Pur.DOOR)) {
            purchases += "DL";
        }
        if (AppConf4Pur.GetProperty(AppConf4Pur.WELL)) {
            purchases += "W";
        }
        if (AppConf4Pur.GetProperty(AppConf4Pur.ELE)) {
            purchases += "E";
        }
		if (AppConf4Pur.GetProperty(AppConf4Pur.T)) {
			purchases += "T";
		}

        // 获取用户id
      //  UserSession userSession = (UserSession) session.getAttribute(Common.sessionUser);
		List<User> users=userMapper.selectList(new QueryWrapper<User>().eq("open_id",oppenId));

        // 查找用户是否被冻结
        User userFro =users.get(0);
        if (!"0".equals(userFro.getFrozen())) {
            message = "您的账户已被冻结！";
            dto.setIssucc(0);
            dto.setError_desc(message);
            return ResponseCode.success(dto);
        } else if ("".equals(resultDeviceCode)) {
            message = "未找到设备！";
            dto.setIssucc(0);
            dto.setError_desc(message);
            return ResponseCode.success(dto);
        } else if ("".equals(resultFacilitiesDesc)) {
            message = "未找到设施！";
            dto.setIssucc(0);
            dto.setError_desc(message);
            return ResponseCode.success(dto);
        } else if (!"1".equals(facilitiesResult.getWorkStatus())) {
            message = "该设施已停用！";
            dto.setIssucc(0);
            dto.setError_desc(message);
            return ResponseCode.success(dto);
        }
        else if (deviceResult.getFacilitiesId() != 0) {
            message = "设备已经被绑定在其他设施上！";
            dto.setIssucc(0);
            dto.setError_desc(message);
            return ResponseCode.success(dto);
        }
//        else if (!mod.equals(resultStrType)) {
//            message = "请绑定工单要求的设备类型！";
//            dto.setIssucc(0);
//            dto.setError_desc(message);
//            return ResponseCode.success(dto);
//        }

//        else if (!purchases.contains(resultStrType)) {
//            message = "请购买对此模块的使用权限！";
//            dto.setIssucc(0);
//            dto.setError_desc(message);
//            return ResponseCode.success(dto);
//        }
        else {

            // 执行绑定
            // 将设施在表中的主键ID存入设备表,记录设备绑定时间
            deviceResult.setFacilitiesId(facilitiesResult.getId());
            deviceResult.setOnline(TimeUtils.getNowDateLong());
            deviceService.updateById(deviceResult);

            // 将经纬度存入设施表
            facilitiesResult.setLongitude(longitude);
            facilitiesResult.setLatitude(latitude);
            // 将定位精度存入设施表的endTime字段中
            facilitiesResult.setEndTime(accuracy);
            // 绑定之后更新时间
            facilitiesResult.setStartTime(TimeUtils.getNowDateLong());

            facilitiesService.updateById(facilitiesResult);

            message = "绑定成功！";
            log.info(message);

            // 在EventLog表中更新工单已处理的数据状态
            EventLog EventLog = eventLogService.getById(eventId);

            EventLog.setDeviceId(deviceResult.getId());
            EventLog.setResult("1");
            EventLog.setEndTime(TimeUtils.getNowDateLong());
            eventLogService.updateById(EventLog);
            log.info("绑定完成后更新EventLog表成功！");

            // 发送短信给负责人
            Module module = moduleService.getById(deviceResult.getModId());
            User user = userMapper.selectById(facilitiesResult.getUserId());
            String msg = "绑定成功";
            Bean4WarnMessInfo info = new Bean4WarnMessInfo(deviceResult.getCode(), module.getName(),
                    facilitiesResult.getDescription(), "", user.getRealName(), user.getPhoneNumber(), msg);
            WarningMass.sendMess(info);


            dto.setIssucc(1);
            dto.setError_desc(msg);
            return ResponseCode.success(dto);
        }

    }
	/**
	 * deviceBind方法中的公共返回消息方法
	 *
	 * @param model model
	 * @param message 要返回给前台的消息
	 * @param returnUrl 要返回的url
	 * @return jumper页面，跳转到该视图
	 */
	private String deviceBindCommonMessage(Model model, String message, String returnUrl) {
		model.addAttribute(ModelAttributeEnum.JUMP_TO_LOWER.getAttributeName(), returnUrl);
		model.addAttribute(ModelAttributeEnum.MESSAGE.getAttributeName(), message);
		log.info(message);
		return ViewNameEnum.JUMPER.getViewName();
	}

	@RequestMapping("/ajaxrefusetounbind")
	public void refusetounbind(Integer eventId, HttpSession session, HttpServletResponse response) {
		String msg = "";
		// 根据事件id查找到对应的事件记录
		EventLog EventLog = eventLogService.getById(eventId);
		// 获取当前时间
		long timeNow = TimeUtils.getNowDateLong();
		EventLog.setEndTime(timeNow);
		// 更新记录
        eventLogService.updateById(EventLog);

		msg = "申请已被拒绝";
		DataResponse.jsonResponse(response, msg);

	}

	@RequestMapping("/ajaxunchainBind")
	public void unchainBind(HttpServletResponse response, String resultStr, Integer facId, Integer deviceId,
			Integer eventId, HttpSession session) {

		// 数据标准化
		resultStr = resultStr.toUpperCase();

		// 通过设备编码和设施id在设备表中查到已被绑定的设备
		QueryWrapper<Device> deviceQueryWrapper = new QueryWrapper<Device>().eq(DeviceFieldEnum.CODE.getFieldName(), resultStr.replace(" ", "")).eq(DeviceFieldEnum.FACILITIES_ID.getFieldName(), facId);
		List<Device> listDev = deviceService.list(deviceQueryWrapper);

		// 获取用户id
		UserSession userSession = (UserSession) session.getAttribute(Common.sessionUser);
		int userId = userSession.getId();
		// 查找用户是否被冻结
		User user = userMapper.selectById(userId);
		if (!user.getFrozen().equals("0")) {
			log.info("您的账户已被冻结");
			DataResponse.jsonResponse(response, "error");
			return;
		} else if (listDev == null || listDev.isEmpty()) {
		    log.info("请扫描正确的二维码");
			DataResponse.jsonResponse(response, "error");
			return;
		} else if (!listDev.get(0).getId().equals(deviceId) ) {
			// 这个else if获取查找到的设备的ID和传过来的deviceId比较，相同则执行解绑操作
            log.info("此条工单记录与扫描到的设备不符");
			DataResponse.jsonResponse(response, "error");
			return;
		} else {

			Device device = listDev.get(0);

			// 将设备中的设施编号，上线时间和结束时间设为0
			device.setFacilitiesId(0);
			device.setOnline(TimeUtils.getNowDateLong());
			device.setEndingTime(0L);

            deviceService.updateById(device);

			// 将工单里对应设施的处理状态置为
			EventLog EventLog = eventLogService.getById(eventId);

			EventLog.setDeviceId(0);
			EventLog.setResult("0");
			EventLog.setEndTime(0L);

			eventLogService.updateById(EventLog);

			// 将此设备解绑前的最新实时状态信息的flag置0，防止出现，设备明明解绑，但是在设备实时状态页面还能显示，并且显示的还一直是解绑前的设施的错误情况
			QueryWrapper<FacMonitoring> facMonitoringQueryWrapper = new QueryWrapper<FacMonitoring>().eq(FacMonitoringFieldEnum.FACID.getFieldName(), deviceId).eq(FacMonitoringFieldEnum.DEVCODE.getFieldName(), device.getCode());
			List<FacMonitoring> facMonitorings = facMonitoringService.list(facMonitoringQueryWrapper);
			if (!facMonitorings.isEmpty()) {
				// 之所以使用foreach，是为了修正数据，如果数据中有一最新实时状态，循环只执行一次。如果数据中有错误导致有多条同一设备的最新记录，刚好在这里把错误的置0
				for (FacMonitoring facmonitoring : facMonitorings) {
					// 从这条记录中找到对应的EventLog,将其中的flag置0并更新数据库
					EventLog tempEventLog = eventLogService.getById(facmonitoring.getEventId());
					tempEventLog.setFlag("0");
					eventLogService.updateById(tempEventLog);
				}

			}

			log.info("解除绑定执行完成");
		}

		DataResponse.jsonResponse(response, "解除绑定执行完成");
		return;
	}

	@ResponseBody
	@RequestMapping("/api/devunbind")
	public ResponseCode unBindApi(String resultStr, Integer facId, Integer devId,
							Integer eventId,String oppenId) {

		BindResDto data=new BindResDto();

		// 数据标准化
		resultStr = resultStr.toUpperCase();

		// 通过设备编码和设施id在设备表中查到已被绑定的设备
		QueryWrapper<Device> deviceQueryWrapper = new QueryWrapper<Device>().eq(DeviceFieldEnum.CODE.getFieldName(), resultStr.replace(" ", "")).eq(DeviceFieldEnum.FACILITIES_ID.getFieldName(), facId);
		List<Device> listDev = deviceService.list(deviceQueryWrapper);

		// 获取用户id
		List<User> users=userMapper.selectList(new QueryWrapper<User>().eq("open_id",oppenId));

		// 查找用户是否被冻结
		User user =users.get(0);
		if (!user.getFrozen().equals("0")) {
			log.info("您的账户已被冻结");
			data.setIssucc(0);
			data.setError_desc("您的账户已被冻结");
			return ResponseCode.success(data);
		} else if (listDev == null || listDev.isEmpty()) {
			log.info("请扫描正确的二维码");
			data.setIssucc(0);
			data.setError_desc("请扫描正确的二维码");
			return ResponseCode.success(data);
		} else if (!listDev.get(0).getId().equals(devId) ) {
			// 这个else if获取查找到的设备的ID和传过来的deviceId比较，相同则执行解绑操作
			log.info("此条工单记录与扫描到的设备不符");
			data.setIssucc(0);
			data.setError_desc("此条工单记录与扫描到的设备不符");
			return ResponseCode.success(data);
		} else {

			Device device = listDev.get(0);

			// 将设备中的设施编号，上线时间和结束时间设为0
			device.setFacilitiesId(0);
			device.setOnline(TimeUtils.getNowDateLong());
			device.setEndingTime(0L);

			deviceService.updateById(device);

			// 将工单里对应设施的处理状态置为
			EventLog EventLog = eventLogService.getById(eventId);

			EventLog.setDeviceId(0);
			EventLog.setResult("0");
			EventLog.setEndTime(0L);

			eventLogService.updateById(EventLog);

			// 将此设备解绑前的最新实时状态信息的flag置0，防止出现，设备明明解绑，但是在设备实时状态页面还能显示，并且显示的还一直是解绑前的设施的错误情况
			QueryWrapper<FacMonitoring> facMonitoringQueryWrapper = new QueryWrapper<FacMonitoring>().eq(FacMonitoringFieldEnum.FACID.getFieldName(), facId);
			//List<FacMonitoring> facMonitorings=facMonitoringMapper.selectList(facMonitoringQueryWrapper);
			List<FacMonitoring> facMonitorings = facMonitoringService.list(facMonitoringQueryWrapper);
			if (!facMonitorings.isEmpty()) {
				// 之所以使用foreach，是为了修正数据，如果数据中有一最新实时状态，循环只执行一次。如果数据中有错误导致有多条同一设备的最新记录，刚好在这里把错误的置0
				for (FacMonitoring facmonitoring : facMonitorings) {
					// 从这条记录中找到对应的EventLog,将其中的flag置0并更新数据库
					EventLog tempEventLog = eventLogService.getById(facmonitoring.getEventId());
					tempEventLog.setFlag("0");
					eventLogService.updateById(tempEventLog);
				}

			}

			log.info("解除绑定执行完成");
		}
		data.setIssucc(1);
		data.setError_desc("解除绑定执行完成");
		return ResponseCode.success(data);

	}

	@RequestMapping("/ajaxagreeunbind")
	public void agreeUnbind(Integer eventId, HttpSession session, HttpServletResponse response) {
		String msg = "";
		// 根据事件id查找到对应的事件记录
		EventLog EventLog = eventLogService.getById(eventId);
		// 获取当前时间
		long timeNow = TimeUtils.getNowDateLong();
		EventLog.setEndTime(timeNow);
		EventLog.setResult("1");
		// 更新记录
        eventLogService.updateById(EventLog);

		// 在这里执行解绑操作，获取设备ID 将设备对应记录中的设施ID设为0
		Device device = deviceService.getById(EventLog.getDeviceId());

		device.setFacilitiesId(0);
        deviceService.updateById(device);

		// 最后为了避免此设备和设施已经解绑但是在绑定这个的施工人的工单上还能看见，需要把显示绑了这个设备已被处理的工单result置0
		int devId = device.getId();


		try {
			QueryWrapper<EventLog> eventLogQueryWrapper = new QueryWrapper<EventLog>().eq(EventLogFieldEnum.DEVICE_ID.getFieldName(), devId).eq(EventLogFieldEnum.RESULT.getFieldName(), "1").eq(EventLogFieldEnum.TYPE_ID.getFieldName(), 1);
			List<EventLog> list = eventLogService.list(eventLogQueryWrapper);

			if (!list.isEmpty()) {

				for (int i = 0; i < list.size(); i++) {
					EventLog e = list.get(i);

					e.setDeviceId(0);
					e.setResult("0");
					e.setEndTime(0L);

					eventLogService.updateById(e);
				}
			}

		} catch (Exception e) {
			log.error("在查找设备对应的已处理的工单时出错");
		}

		// 将此设备解绑前的最新实时状态信息的flag置0，防止出现，设备明明解绑，但是在设备实时状态页面还能显示，并且显示的还一直是解绑前的设施的错误情况
		List<FacMonitoring> facMonitorings = new ArrayList<>();
		QueryWrapper<FacMonitoring> facMonitoringQueryWrapper = new QueryWrapper<FacMonitoring>().eq(FacMonitoringFieldEnum.DEVID.getFieldName(), devId).eq(FacMonitoringFieldEnum.DEVCODE.getFieldName(), device.getCode());
		try {
			facMonitorings = facMonitoringService.list(facMonitoringQueryWrapper);
		} catch (Exception e) {
		    log.error("在查询实时监测状态页面的视图时出错");
		}

		if (!facMonitorings.isEmpty()) {
			// 之所以使用foreach，是为了修正数据，如果数据中有一最新实时状态，循环只执行一次。如果数据中有错误导致有多条同一设备的最新记录，刚好在这里把错误的置0
			for (FacMonitoring facmonitoring : facMonitorings) {
				// 从这条记录中找到对应的EventLog,将其中的flag置0并更新数据库
				EventLog tempEventLog = eventLogService.getById(facmonitoring.getEventId());

				tempEventLog.setFlag("0");
//				EventLogDao.update(tempEventLog);
                eventLogService.updateById(tempEventLog);
			}

		}
		msg = "绑定已经解除";
		DataResponse.jsonResponse(response, msg);
	}

	@RequestMapping("/{role}/unbindopinion")
	public String unbindopinion(String condition, HttpSession session, Model model, HttpServletRequest request) {
		commonModelAdd(model, BasePathCollector.getBasePathWithoutPort(request), "解绑申请");
		model.addAttribute(ModelAttributeEnum.CONDITION.getAttributeName(), condition);
		UserSession userSession = (UserSession) session.getAttribute(Common.sessionUser);
		if (userSession != null) {
			int userId = userSession.getId();

			User userFro = userMapper.selectById(userId);
			if (!userFro.getFrozen().equals("0")) {

				model.addAttribute(ModelAttributeEnum.MESSAGE.getAttributeName(), "您的账号已被冻结");
				model.addAttribute(ModelAttributeEnum.JUMP_TO_LOWER.getAttributeName(), BasePathCollector.getBasePath(request) + "3/applyunbind.do");
				return ViewNameEnum.JUMPER.getViewName();
			}

			String timeNow = String.valueOf(TimeUtils.getNowDateLong());

			// 获取其他用户对该用户发出的解绑申请
			QueryWrapper<UnbindOpinion> unbindOpinionQueryWrapper = new QueryWrapper<UnbindOpinion>().eq(UnbindOpinionFieldEnum.USERID.getFieldName(), userId).eq(UnbindOpinionFieldEnum.TYPEID.getFieldName(), 5).gt(UnbindOpinionFieldEnum.ENDTIME.getFieldName(), timeNow);
			if (StringUtils.isNotEmpty(condition)) {
				unbindOpinionQueryWrapper.like(UnbindOpinionFieldEnum.DEVCODE.getFieldName(), condition);
			}
			List<UnbindOpinion> list = unbindOpinionService.list(unbindOpinionQueryWrapper);
			model.addAttribute("list", list);
		}

		return "wechat/unbindopinion";
	}

	@RequestMapping("/{role}/applyunbind")
	public String applyUnbind(HttpSession session, Model model, String condition, HttpServletRequest request) {
		UserSession user = (UserSession) session.getAttribute(Common.sessionUser);
		commonModelAdd(model, BasePathCollector.getBasePathWithoutPort(request), "故障处理");
		if (user != null) {

			QueryWrapper<DeviceFacility> deviceFacilityQueryWrapper = new QueryWrapper<DeviceFacility>().gt(DeviceFacilityFieldEnum.DEVID.getFieldName(), 0).eq(DeviceFacilityFieldEnum.FACWORKSTU.getFieldName(), 1).eq(DeviceFacilityFieldEnum.REGIONID.getFieldName(), user.getRegionId());
			if (StringUtils.isNotEmpty(condition)) deviceFacilityQueryWrapper.nested(i -> i.like(DeviceFacilityFieldEnum.DEVCODE.getFieldName(), condition).or().like(DeviceFacilityFieldEnum.REALNAME.getFieldName(), condition));
			List<DeviceFacility> deviceFacilities = deviceFacilityService.list(deviceFacilityQueryWrapper);
			model.addAttribute("list", deviceFacilities);
		}

		return "wechat/applyunbind";
	}

	/**
	 * 添加公共的model属性
	 *
	 * @param model model
	 * @param basePathWithoutPort basePath
	 * @param title pageTitle和subTitle的名称
	 */
	private void commonModelAdd(Model model, String basePathWithoutPort, String title) {
		model.addAttribute(ModelAttributeEnum.BASE_PATH.getAttributeName(), basePathWithoutPort);
		model.addAttribute(ModelAttributeEnum.PAGE_TITLE.getAttributeName(), title);
		model.addAttribute(ModelAttributeEnum.SUB_TITLE.getAttributeName(), title);
	}

	@RequestMapping("/ajaxaddanotherunbind")
	public void addAnotherUnbind(Integer modId, Integer deviceId, Integer facId, HttpSession session,
			HttpServletResponse response) {
		String msg = "";

		// 查询此用户是否被冻结
		// 获取用户id
		UserSession userSession = (UserSession) session.getAttribute(Common.sessionUser);
		int userId = userSession.getId();
		// 查找用户是否被冻结
		User userFro = userMapper.selectById(userId);
		if (!userFro.getFrozen().equals("0")) {

			msg = "您的账号已被冻结";
			log.info(msg);
			DataResponse.jsonResponse(response, msg);
			return;
		}

		// 根据设施id查询到对应设施的负责人的Id
		Facilities facilities = facilitiesService.getById(facId);
		int facUser = facilities.getUserId();

		// 查询是否重复申请
		List<EventLog> list = new ArrayList<>();

		String timeNow = String.valueOf(TimeUtils.getNowDateLong());

		try {
			QueryWrapper<EventLog> eventLogQueryWrapper = new QueryWrapper<EventLog>().eq(EventLogFieldEnum.MODULE_ID.getFieldName(), modId)
					.eq(EventLogFieldEnum.DEVICE_ID.getFieldName(), deviceId)
					.eq(EventLogFieldEnum.FACILITIES_ID.getFieldName(), facId)
					.eq(EventLogFieldEnum.USER_ID.getFieldName(), facUser)
					.eq(EventLogFieldEnum.TYPE_ID.getFieldName(), 5)
					.eq(EventLogFieldEnum.RESULT.getFieldName(), '0')
					.gt(EventLogFieldEnum.END_TIME.getFieldName(), timeNow)
					.eq(EventLogFieldEnum.EXTENSION.getFieldName(), userSession.getName());
			list = eventLogService.list(eventLogQueryWrapper);
		} catch (Exception e) {
			log.error("查询重复申请遇到异常！");
		}

		// 判断是否重复申请，如果是，则提示重复申请，如果数据库有多条重复申请记录则删除多余条数
		if (list != null && !list.isEmpty()) {

			for (int i = 1; i < list.size(); i++) {
                eventLogService.removeById(list.get(i).getId());
			}

			msg = "您不能重复添加申请";
			log.info(msg);
			DataResponse.jsonResponse(response, msg);
			return;
		} else {
			// 向EventLog中添加申请记录

			// 计算当前时间和1天后时间
			long tempNow = TimeUtils.getNowDateLong();
			long time1day = tempNow + (3600 * 24 * 1000);

			// user_id字段表示向谁发出申请，extension字段填入这条申请发起人的姓名，仅对申请解绑别人的设备有效
			EventLog eventLog = new EventLog(null, modId, deviceId, facId, facUser, 0, 5, "", "", "", "0", tempNow,
					time1day, userSession.getName(), "");

            eventLogService.save(eventLog);
			msg = "您已添加申请";
			log.info(msg);
			DataResponse.jsonResponse(response, msg);
			return;
		}

	}

	@RequestMapping("/ajaxmodifyfault")
	public void modifyFault(HttpServletResponse response, Integer eventId) {
		EventLog eventLog = eventLogService.getById(eventId);
		eventLog.setResult("1");
		eventLog.setEndTime(System.currentTimeMillis());
		boolean update = eventLogService.updateById(eventLog);
		int number;
		if (update) number = 1;
		else number = 0;
		DataResponse.jsonResponse(response, number);
	}

	@RequestMapping("/ajaxapplytempauth")
	public void applyTempAuth(String openid, String devCode, HttpServletResponse response) {

		String tempMsg = "";
		// 通过设备code查找device表中对应记录
		QueryWrapper<Device> deviceQueryWrapper = new QueryWrapper<Device>().eq(DeviceFieldEnum.CODE.getFieldName(), devCode);
		List<Device> listDevice = deviceService.list(deviceQueryWrapper);

		Device device = null;
		if (listDevice != null && !listDevice.isEmpty()) {
			device = listDevice.get(0);
		}
		int deviceId = device.getId();
		// 根据devCode查询属于哪一个module
		String typeDev = devCode.substring(0, 1);
		QueryWrapper<Module> moduleQueryWrapper = new QueryWrapper<Module>().eq(ModuleFieldEnum.CODE.getFieldName(), typeDev);
		List<Module> listMod = moduleService.list(moduleQueryWrapper);
		Module module = null;
		if (listMod != null && !listMod.isEmpty()) {
			module = listMod.get(0);
		}
		int modId = module.getId();

		// 通过openid找到对应的用户
		Map<String, Object> paramUser = new HashMap<>();
		paramUser.put(UserFieldEnum.OPEN_ID.getFieldName(), openid);
		List<User> userList = userMapper.selectByMap(paramUser);
		Integer tempOperatorId = userList.get(0).getId();
		String frozen = userList.get(0).getFrozen();
		log.info("执行AddOperator的execute()");
		log.info("deviceId:" + deviceId);
		log.info("modId:" + modId);
		log.info("tempOperatorId:" + tempOperatorId);
		// @Value("${tempTime}")
		int tempTime = 4;
		log.info("tempTime:" + tempTime);

		/*
		 * 如果传入的userID不等于0,并且用户未被冻结，发出申请
		 */
		if (tempOperatorId != 0 && frozen.equals("0")) {

			long timeLong = TimeUtils.getNowDateLong();
			// 设施和操作人都是有效的话，则存入数据库

			QueryWrapper<EventLog> eventLogQueryWrapper = new QueryWrapper<EventLog>().eq(EventLogFieldEnum.DEVICE_ID.getFieldName(), deviceId)
					.eq(EventLogFieldEnum.USER_ID.getFieldName(), tempOperatorId)
					.eq(EventLogFieldEnum.TYPE_ID.getFieldName(), 4);
			List<EventLog> listTemp = eventLogService.list(eventLogQueryWrapper);
			for (EventLog eventLog : listTemp) {
				eventLog.setEndTime(timeLong);
				eventLog.setFlag("0");
                eventLogService.updateById(eventLog);
			}

			EventLog eventLog = new EventLog(null, modId, listDevice.get(0).getId(), 0, tempOperatorId, 0, 4, "", "",
					"", "0", timeLong, timeLong + tempTime * 3600 * 1000, "", "1");
            eventLogService.save(eventLog);
			tempMsg = "申请已发出！";
			DataResponse.jsonResponse(response, tempMsg);
			return;
		}
		tempMsg = "申请未发出";
		DataResponse.jsonResponse(response, tempMsg);

	}

	@ResponseBody
	@RequestMapping("/api/applyunlock")
	public ResponseCode applyUnlock(String oppenId, String devCode){
		String tempMsg = "";
		// 通过设备code查找device表中对应记录
		QueryWrapper<Device> deviceQueryWrapper = new QueryWrapper<Device>().eq(DeviceFieldEnum.CODE.getFieldName(), devCode);
		List<Device> listDevice = deviceService.list(deviceQueryWrapper);

		Device device = null;
		if (listDevice != null && !listDevice.isEmpty()) {
			device = listDevice.get(0);
		}
		int deviceId = device.getId();
		// 根据devCode查询属于哪一个module
		//String typeDev = devCode.substring(0, 1);
		QueryWrapper<Module> moduleQueryWrapper = new QueryWrapper<Module>().eq(ModuleFieldEnum.ID.getFieldName(), device.getModId());
		List<Module> listMod = moduleService.list(moduleQueryWrapper);
		Module module = null;
		if (listMod != null && !listMod.isEmpty()) {
			module = listMod.get(0);
		}
		int modId = module.getId();

		// 通过openid找到对应的用户
		Map<String, Object> paramUser = new HashMap<>();
		paramUser.put(UserFieldEnum.OPEN_ID.getFieldName(), oppenId);
		List<User> userList = userMapper.selectByMap(paramUser);
		Integer tempOperatorId = userList.get(0).getId();
		String frozen = userList.get(0).getFrozen();
		log.info("执行AddOperator的execute()");
		log.info("deviceId:" + deviceId);
		log.info("modId:" + modId);
		log.info("tempOperatorId:" + tempOperatorId);
		// @Value("${tempTime}")
		Long tempTime = 4l;
		log.info("tempTime:" + tempTime);

		List<ApplyRecord> records=applyRecordMapper.selectList(new QueryWrapper<ApplyRecord>().eq("devCode",devCode).eq("userId",userList.get(0).getId()));
		if(records.size()!=0){
			tempMsg = "已经申请！";
			return ResponseCode.success(tempMsg);
		}
		/*
		 * 如果传入的userID不等于0,并且用户未被冻结，发出申请
		 */
		if (tempOperatorId != 0 && frozen.equals("0")) {

			long timeLong = TimeUtils.getNowDateLong();
			// 设施和操作人都是有效的话，则存入数据库

			QueryWrapper<EventLog> eventLogQueryWrapper = new QueryWrapper<EventLog>().eq(EventLogFieldEnum.DEVICE_ID.getFieldName(), deviceId)
					.eq(EventLogFieldEnum.USER_ID.getFieldName(), tempOperatorId)
					.eq(EventLogFieldEnum.TYPE_ID.getFieldName(), 4);
			List<EventLog> listTemp = eventLogService.list(eventLogQueryWrapper);
			for (EventLog eventLog : listTemp) {
				eventLog.setEndTime(timeLong);
				eventLog.setFlag("0");
				eventLogService.updateById(eventLog);
			}
			Long endTime=timeLong+ tempTime * 3600l * 1000l;
			EventLog eventLog = new EventLog(null, modId, listDevice.get(0).getId(), 0, tempOperatorId, 0, 4, "", "",
					"", "0", timeLong, endTime, "", "1");
			eventLogService.save(eventLog);
			tempMsg = "申请已发出！";
			return ResponseCode.success(tempMsg);
		}
		tempMsg = "申请未发出";
		return ResponseCode.success(tempMsg);
	}

	// 获取已经存在的token并查看是否可用
	@RequestMapping("/OpenDoor_{devCode}.do")
	public String openDoor(@PathVariable("devCode") String devCode, HttpServletRequest request, Model model) {
		String url = "" + BasePathCollector.getBasePathWithoutPort(request) + "OpenTheDoor?devCode=" + devCode;
		String codeUrl = WeiXinAuthorization.getCodeUrl(weChat.getAppId(), url, WeiXinAuthorization.SNSAPI_USERINFO);
		model.addAttribute(ModelAttributeEnum.JUMP_TO_LOWER.getAttributeName(), codeUrl);
		return "jumperatonce";
	}

	/**
	 * 设备扫码开锁时进入这个方法，转发给unlocker方法进行开门请求的处理
	 *
	 * @param code 微信扫描的二维码
	 * @param devCode 设备码
	 * @param request request请求
	 * @param model model模型
	 * @return 返回开门结果的提示信息
	 */
	@RequestMapping("/OpenTheDoor")
	public String openTheDoor(String code, String devCode, HttpServletRequest request, Model model) {

		Oauth2AccessToken oauth2AccessToken = WeiXinAuthorization.getOauth2AccessToken(weChat.getAppId(),
				weChat.getAppSecret(), code);
		String openId = oauth2AccessToken.getOpenid();

		// 转发给unlocker方法
		String message = open(devCode, openId, request);

		message = message.replaceAll("\"", "");

		if (message.equals("0")) {
			message = "没有开锁权限";
		} else if (message.equals("")) {
			message = "未能发送开锁请求";
		}

		model.addAttribute(ModelAttributeEnum.MESSAGE.getAttributeName(), message);

		return ViewNameEnum.WECHAT_MESSAGE.getViewName();
	}

	/**
	 * 处理开门请求
	 *
	 * @param devCode device表的code，设备码
	 * @param openId user表的openid，微信id
	 * @param response 用于返回消息
	 */
	@GetMapping("/unlockdoor")
	public void unlockDoor(String devCode, String openId, HttpServletResponse response) {

		String unlockMsg = "";

        // 根据openid查询用户
		QueryWrapper<User> userQueryWrapper = new QueryWrapper<User>().eq(UserFieldEnum.OPEN_ID.getFieldName(), openId);
		User user = userService.getOne(userQueryWrapper);

		if (user == null) {
			unlockMsg = "您未注册";
		} else if (!user.getFrozen().equals("0")) {
			unlockMsg = "您的账号已被冻结";
		} else {
			unlockMsg = handleUserOpenDoor(devCode, unlockMsg, user);
		}
		DataResponse.jsonResponse(response, unlockMsg);
	}

	@ResponseBody
	@GetMapping("/api/unlock")
	public ResponseCode unlockNbDoor(String devCode, String oppenId){
		String unlockMsg = "";
		BindResDto data=new BindResDto();
		// 根据openid查询用户
		QueryWrapper<User> userQueryWrapper = new QueryWrapper<User>().eq(UserFieldEnum.OPEN_ID.getFieldName(), oppenId);
		User user = userService.getOne(userQueryWrapper);
		data.setIssucc(0);
		if (user == null) {
			unlockMsg = "您未注册";
		} else if (!user.getFrozen().equals("0")) {
			unlockMsg = "您的账号已被冻结";
		} else {
			unlockMsg = handleUserOpenDoor(devCode, unlockMsg, user);
			if(unlockMsg.equals("已发送开门请求")){
				data.setIssucc(1);
				data.setError_desc(unlockMsg);
				return ResponseCode.success(data);
			}
		}

		data.setError_desc(unlockMsg);
		return ResponseCode.error(data);
	}
	/**
	 * 确认登录的用户可用后，进行该部分逻辑处理
	 *
	 * @param devCode 设备码
	 * @param unlockMsg 解锁的提示消息
	 * @param user 登录的用户实体
	 * @return 返回提示信息
	 */
	private String handleUserOpenDoor(String devCode, String unlockMsg, User user) {
		/* 用户已注册,获取用户实体 */

		/* 判断devCode是合法字符 */
		devCode = devCode.toUpperCase();
		QueryWrapper<Device> deviceQueryWrapper = new QueryWrapper<>();
		deviceQueryWrapper.eq("code", devCode);
		Device device = deviceMapper.selectOne(deviceQueryWrapper);
		if (device.getModId()!=1) {
			unlockMsg = "此设备无效";
		} else {
			// 根据设备码查找设备
			if (device == null) {
				unlockMsg = "此设备未上线";
			} else {
				// 根据设备找到设施且设备被绑定，进入余下操作
				int facId = device.getFacilitiesId();
				if (facId == 0) {
					unlockMsg = "此设备未被绑定";
				} else {
					unlockMsg = handleFacilityBind(devCode, unlockMsg, user, device, facId);
				}
			}
		}
		return unlockMsg;
	}

	/**
	 * 当确认设备已经绑定设施后，进行该部分逻辑处理
	 *
	 * @param devCode 设备码
	 * @param unlockMsg 解锁后的提示信息
	 * @param user 登录成功的用户实体
	 * @param device 用户扫描后，要开门的设备实体
	 * @param facId 设备对应的设施的id
	 * @return 返回提示信息
	 */
	private String handleFacilityBind(String devCode, String unlockMsg, User user, Device device, int facId) {
		/* 判断当前用户是否是此设施的负责人或是开门人，如果是则可以开锁 */
		/* 根据设施ID找到设施 */
		Facilities facilities = facilitiesService.getById(facId);
		/* 判断设施的工作状态 */
		if (!facilities.getWorkStatus().equals("1")) {
			unlockMsg = "此设施已经被停用";
		} else if (!user.getRegionId().equals(facilities.getRegionId())) {
			// 判断开锁人是否和该设施属于同一区域
			unlockMsg = "用户和设施不在同一区";
		} else {

			// 获取当前设备的id,code和当前人的id和code
			int devId = device.getId();
			int userId = user.getId();
			String userRealName = user.getRealName();

			// 判断扫码人是不是属于该设施的负责人
			if (!user.getId().equals(facilities.getUserId())) {

				// 如果不是，则判断扫码人是不是属于该设备的开门人
				QueryWrapper<AccessControl> accessControlQueryWrapper = new QueryWrapper<>();
				accessControlQueryWrapper.eq(AccessControlFieldEnum.USER_ID.getFieldName(), userId)
						.eq(AccessControlFieldEnum.DEVICE_ID.getFieldName(), devId);
				AccessControl accessControl = accessControlService.getOne(accessControlQueryWrapper);

				// 如果门禁表中存在该记录且用户权限未失效，就处理开门请求
				boolean isOpenerAndNotExpired = accessControl != null
						&& accessControl.getDeadLine() != null
						&& LocalDate.now().isBefore(accessControl.getDeadLine());
				if(device.getModId()==1){
                    unlockMsg = isOpenerAndNotExpired ?nbHandleOpenDoor(device,facilities, userId,unlockMsg,device.getLevel()) : "用户没有权限或权限过期";
                }else{
                    unlockMsg = isOpenerAndNotExpired ? handleOpenDoor(devCode, unlockMsg, devId, userId, userRealName) : "用户没有权限或权限过期";
                }
			} else {
				// 如果是此设施的负责人，则直接处理机房和机柜的开锁命令
                if(device.getModId()==1){
                    unlockMsg = nbHandleOpenDoor(device, facilities,userId,unlockMsg,device.getLevel());
                }else{
                    unlockMsg = handleOpenDoor(devCode, unlockMsg, devId, userId, userRealName);
                }
			}
		}
		return unlockMsg;
	}

	/**
	 * 处理unlockDoor方法中的开门逻辑，直接向连接组件发起请求
	 *
	 * @param devCode 设备码
	 * @param unlockMsg 解锁后的提示信息
	 * @param devId 设备id
	 * @param userId 用户id
	 * @param userRealname 用户真实姓名
	 * @return 将连接组件处理请求的结果提示返回
	 */
	private String handleOpenDoor(String devCode, String unlockMsg, int devId, int userId, String userRealname) {
		if (devCode.substring(0, 1).equals("L")) {
			/* 此用户是设施的临时操作人，则将信息存入缓存 */
			DeviceCache deviceCache = DeviceCache.getInstance();
			deviceCache.newWait4Open(devCode);
			// 将该设备与对应的当前操作该设备的操作人放入内存中，在收到开锁成功的反馈之后取出做操作
			Stack4LockOpener.doOneRequest(devCode, devId, userRealname, userId);

			unlockMsg = "灯不闪时按锁开门";
		} else if (devCode.substring(0, 1).equals("D")) {

			// 直接发送开门请求
			ServerDownriverMsgHttp sdm = new ServerDownriverMsgHttp();

			String resp = sdm.HttpRequest(Urloader.getUrlProperty("serverdownriverurl"),
					"(" + devCode + ",08,O)", String.valueOf(TimeUtils.getNowDateLong()));

			if (resp.equals("ok")) {
				// 将该设备与对应的操作人放入内存中，在收到开锁成功的反馈之后取出做操作
				Stack4LockOpener.doOneRequest(devCode, devId, userRealname, userId);
				unlockMsg = "已发送开门请求";
			} else {
				unlockMsg = "打开门失败,可能设备断电";
			}
		}
		return unlockMsg;
	}

    /**
     * nb
     * @param
     * @param unlockMsg
     * @return
     */

    private String nbHandleOpenDoor(Device device, Facilities facilities,int userId,String unlockMsg,Integer level) {
    	EventLog eventLog=new EventLog();
    	eventLog.setDeviceStatus("1");
		eventLog.setModuleId(1);
		eventLog.setStartTime(LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8"))*1000);
		eventLog.setEndTime(LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8"))*1000);
		eventLog.setFlag("0");
		eventLog.setDeviceId(device.getId());
		eventLog.setFacilitiesId(facilities.getId());
		eventLog.setExtension("");
		eventLog.setDoorStatus("");
		eventLog.setFaultTypeId(21);
		eventLog.setTypeId(7);
		eventLog.setUserId(userId);
		eventLog.setElectricity("");
		eventLog.setResult("1");
		eventLogService.save(eventLog);
    	if(level==0){
			doorController.doorUnlock(device.getInternetDeviceId());
			unlockMsg = "已发送开门请求";
		}else{
			String url = "http://127.0.0.1:8081/opendoors";
			RestTemplate client = new RestTemplate();
			HttpHeaders headers = new HttpHeaders();
		// 提交方式都是表单提交
			headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
		//  封装参数，千万不要替换为Map与HashMap，否则参数无法传递
			MultiValueMap<String, String> params= new LinkedMultiValueMap<String, String>();
		//  也支持中文
			params.add("internetDevId", device.getInternetDeviceId());
			HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<MultiValueMap<String, String>>(params, headers);
		//  执行HTTP请求
			ResponseEntity<Integer> response = client.exchange(url, HttpMethod.POST, requestEntity, Integer.class);
		//  输出结果
			Integer res=response.getBody().intValue();
			if(res==0){
				unlockMsg = "已发送开门请求";
			}else{
				unlockMsg = "发送开门请求失败";
			}
		}

        return unlockMsg;
    }
	/**
	 * 在openTheDoor方法中，使用该方法调用unlockDoor方法处理开门逻辑
	 *
	 * @param devCode 设备码
	 * @param openId 用户微信的openId
	 * @param request  request请求
	 * @return 返回提示信息
	 */
	private String open(String devCode, String openId, HttpServletRequest request) {
		// 添加开锁逻辑
		String url = BasePathCollector.getBasePathWithoutPort(request) + "unlockdoor?devCode=" + devCode + "&openId="
				+ openId;

		// 返回提示信息
		return httpRequestGet(url);
	}

	/**
	 * 这个方法用来调用微信端开门请求,GET
	 * 
	 * @param url 处理开门请求的url
	 * @return 处理结果的提示信息
	 */
	private String httpRequestGet(String url) {

		URL url2;
		StringBuilder sb = new StringBuilder();
		String str = "";
		try {
			url2 = new URL(url);
			HttpURLConnection connection = (HttpURLConnection) url2.openConnection();
			connection.setDoOutput(true);
			connection.setDoInput(true);
			connection.setRequestMethod("GET");
			connection.connect();

			// 获取此处请求之后被回复的信息
			InputStream inputStream = connection.getInputStream();

			BufferedReader br = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
			String temp = "";
			while ((temp = br.readLine()) != null) {
				sb.append(temp);
			}

			str = sb.toString();

			inputStream.close();
			br.close();
		} catch (Exception e) {
			log.error("在OpenTheDoor中执行httpRequest失败");
		}
		return str;
	}
}
